home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / Mesa-3.0 / SRC / VARRAY.C < prev    next >
Encoding:
C/C++ Source or Header  |  1998-09-01  |  44.3 KB  |  1,424 lines

  1. /* $Id: varray.c,v 3.7 1998/09/01 03:05:22 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  3.0
  6.  * Copyright (C) 1995-1998  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: varray.c,v $
  26.  * Revision 3.7  1998/09/01 03:05:22  brianp
  27.  * fixed interleaved texture coordinate problem
  28.  *
  29.  * Revision 3.6  1998/08/21 01:50:53  brianp
  30.  * added support for texture coordinate set interleave factor
  31.  *
  32.  * Revision 3.5  1998/06/07 22:18:52  brianp
  33.  * implemented GL_EXT_multitexture extension
  34.  *
  35.  * Revision 3.4  1998/03/27 04:26:44  brianp
  36.  * fixed G++ warnings
  37.  *
  38.  * Revision 3.3  1998/02/20 04:53:07  brianp
  39.  * implemented GL_SGIS_multitexture
  40.  *
  41.  * Revision 3.2  1998/02/01 20:05:10  brianp
  42.  * added glDrawRangeElements()
  43.  *
  44.  * Revision 3.1  1998/02/01 16:37:19  brianp
  45.  * added GL_EXT_rescale_normal extension
  46.  *
  47.  * Revision 3.0  1998/01/31 21:06:45  brianp
  48.  * initial rev
  49.  *
  50.  */
  51.  
  52.  
  53.  
  54. /*
  55.  * NOTE:  At this time, only three vertex array configurations are optimized:
  56.  *  1.  glVertex3fv(), zero stride
  57.  *  2.  glNormal3fv() with glVertex3fv(), zero stride
  58.  *  3.  glNormal3fv() with glVertex4fv(), zero stride
  59.  *
  60.  * More optimized array configurations can be added.
  61.  */
  62.  
  63.  
  64. #ifdef PC_HEADER
  65. #include "all.h"
  66. #else
  67. #include <stdlib.h>
  68. #include <string.h>
  69. #include "context.h"
  70. #include "enable.h"
  71. #include "dlist.h"
  72. #include "light.h"
  73. #include "macros.h"
  74. #include "texstate.h"
  75. #include "types.h"
  76. #include "varray.h"
  77. #include "vb.h"
  78. #include "vbfill.h"
  79. #include "vbrender.h"
  80. #include "vbxform.h"
  81. #include "xform.h"
  82. #endif
  83.  
  84.  
  85. void gl_VertexPointer( GLcontext *ctx,
  86.                        GLint size, GLenum type, GLsizei stride,
  87.                        const GLvoid *ptr )
  88. {
  89.    if (size<2 || size>4) {
  90.       gl_error( ctx, GL_INVALID_VALUE, "glVertexPointer(size)" );
  91.       return;
  92.    }
  93.    if (stride<0) {
  94.       gl_error( ctx, GL_INVALID_VALUE, "glVertexPointer(stride)" );
  95.       return;
  96.    }
  97.    switch (type) {
  98.       case GL_SHORT:
  99.          ctx->Array.VertexStrideB = stride ? stride : size*sizeof(GLshort);
  100.          break;
  101.       case GL_INT:
  102.          ctx->Array.VertexStrideB = stride ? stride : size*sizeof(GLint);
  103.          break;
  104.       case GL_FLOAT:
  105.          ctx->Array.VertexStrideB = stride ? stride : size*sizeof(GLfloat);
  106.          break;
  107.       case GL_DOUBLE:
  108.          ctx->Array.VertexStrideB = stride ? stride : size*sizeof(GLdouble);
  109.          break;
  110.       default:
  111.          gl_error( ctx, GL_INVALID_ENUM, "glVertexPointer(type)" );
  112.          return;
  113.    }
  114.    ctx->Array.VertexSize = size;
  115.    ctx->Array.VertexType = type;
  116.    ctx->Array.VertexStride = stride;
  117.    ctx->Array.VertexPtr = (void *) ptr;
  118. }
  119.  
  120.  
  121.  
  122.  
  123. void gl_NormalPointer( GLcontext *ctx,
  124.                        GLenum type, GLsizei stride, const GLvoid *ptr )
  125. {
  126.    if (stride<0) {
  127.       gl_error( ctx, GL_INVALID_VALUE, "glNormalPointer(stride)" );
  128.       return;
  129.    }
  130.    switch (type) {
  131.       case GL_BYTE:
  132.          ctx->Array.NormalStrideB = stride ? stride : 3*sizeof(GLbyte);
  133.          break;
  134.       case GL_SHORT:
  135.          ctx->Array.NormalStrideB = stride ? stride : 3*sizeof(GLshort);
  136.          break;
  137.       case GL_INT:
  138.          ctx->Array.NormalStrideB = stride ? stride : 3*sizeof(GLint);
  139.          break;
  140.       case GL_FLOAT:
  141.          ctx->Array.NormalStrideB = stride ? stride : 3*sizeof(GLfloat);
  142.          break;
  143.       case GL_DOUBLE:
  144.          ctx->Array.NormalStrideB = stride ? stride : 3*sizeof(GLdouble);
  145.          break;
  146.       default:
  147.          gl_error( ctx, GL_INVALID_ENUM, "glNormalPointer(type)" );
  148.          return;
  149.    }
  150.    ctx->Array.NormalType = type;
  151.    ctx->Array.NormalStride = stride;
  152.    ctx->Array.NormalPtr = (void *) ptr;
  153. }
  154.  
  155.  
  156.  
  157. void gl_ColorPointer( GLcontext *ctx,
  158.                       GLint size, GLenum type, GLsizei stride,
  159.                       const GLvoid *ptr )
  160. {
  161.    if (size<3 || size>4) {
  162.       gl_error( ctx, GL_INVALID_VALUE, "glColorPointer(size)" );
  163.       return;
  164.    }
  165.    if (stride<0) {
  166.       gl_error( ctx, GL_INVALID_VALUE, "glColorPointer(stride)" );
  167.       return;
  168.    }
  169.    switch (type) {
  170.       case GL_BYTE:
  171.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLbyte);
  172.          break;
  173.       case GL_UNSIGNED_BYTE:
  174.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLubyte);
  175.          break;
  176.       case GL_SHORT:
  177.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLshort);
  178.          break;
  179.       case GL_UNSIGNED_SHORT:
  180.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLushort);
  181.          break;
  182.       case GL_INT:
  183.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLint);
  184.          break;
  185.       case GL_UNSIGNED_INT:
  186.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLuint);
  187.          break;
  188.       case GL_FLOAT:
  189.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLfloat);
  190.          break;
  191.       case GL_DOUBLE:
  192.          ctx->Array.ColorStrideB = stride ? stride : size*sizeof(GLdouble);
  193.          break;
  194.       default:
  195.          gl_error( ctx, GL_INVALID_ENUM, "glColorPointer(type)" );
  196.          return;
  197.    }
  198.    ctx->Array.ColorSize = size;
  199.    ctx->Array.ColorType = type;
  200.    ctx->Array.ColorStride = stride;
  201.    ctx->Array.ColorPtr = (void *) ptr;
  202. }
  203.  
  204.  
  205.  
  206. void gl_IndexPointer( GLcontext *ctx,
  207.                       GLenum type, GLsizei stride, const GLvoid *ptr )
  208. {
  209.    if (stride<0) {
  210.       gl_error( ctx, GL_INVALID_VALUE, "glIndexPointer(stride)" );
  211.       return;
  212.    }
  213.    switch (type) {
  214.       case GL_SHORT:
  215.          ctx->Array.IndexStrideB = stride ? stride : sizeof(GLbyte);
  216.          break;
  217.       case GL_INT:
  218.          ctx->Array.IndexStrideB = stride ? stride : sizeof(GLint);
  219.          break;
  220.       case GL_FLOAT:
  221.          ctx->Array.IndexStrideB = stride ? stride : sizeof(GLfloat);
  222.          break;
  223.       case GL_DOUBLE:
  224.          ctx->Array.IndexStrideB = stride ? stride : sizeof(GLdouble);
  225.          break;
  226.       default:
  227.          gl_error( ctx, GL_INVALID_ENUM, "glIndexPointer(type)" );
  228.          return;
  229.    }
  230.    ctx->Array.IndexType = type;
  231.    ctx->Array.IndexStride = stride;
  232.    ctx->Array.IndexPtr = (void *) ptr;
  233. }
  234.  
  235.  
  236.  
  237. void gl_TexCoordPointer( GLcontext *ctx,
  238.                          GLint size, GLenum type, GLsizei stride,
  239.                          const GLvoid *ptr )
  240. {
  241.    GLuint texSet = ctx->TexCoordSet;
  242.    if (size<1 || size>4) {
  243.       gl_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(size)" );
  244.       return;
  245.    }
  246.    if (stride<0) {
  247.       gl_error( ctx, GL_INVALID_VALUE, "glTexCoordPointer(stride)" );
  248.       return;
  249.    }
  250.    switch (type) {
  251.       case GL_SHORT:
  252.          ctx->Array.TexCoordStrideB[texSet] = stride ? stride : size*sizeof(GLshort);
  253.          break;
  254.       case GL_INT:
  255.          ctx->Array.TexCoordStrideB[texSet] = stride ? stride : size*sizeof(GLint);
  256.          break;
  257.       case GL_FLOAT:
  258.          ctx->Array.TexCoordStrideB[texSet] = stride ? stride : size*sizeof(GLfloat);
  259.          break;
  260.       case GL_DOUBLE:
  261.          ctx->Array.TexCoordStrideB[texSet] = stride ? stride : size*sizeof(GLdouble);
  262.          break;
  263.       default:
  264.          gl_error( ctx, GL_INVALID_ENUM, "glTexCoordPointer(type)" );
  265.          return;
  266.    }
  267.    ctx->Array.TexCoordSize[texSet] = size;
  268.    ctx->Array.TexCoordType[texSet] = type;
  269.    ctx->Array.TexCoordStride[texSet] = stride;
  270.    ctx->Array.TexCoordPtr[texSet] = (void *) ptr;
  271. }
  272.  
  273.  
  274.  
  275. /* GL_SGIS_multitexture ONLY!!! */
  276. void gl_MultiTexCoordPointer( GLcontext *ctx, GLenum target,
  277.                               GLint size, GLenum type, GLsizei stride,
  278.                               const GLvoid *ptr )
  279. {
  280.    GLuint texSet;
  281.    if (target < GL_TEXTURE0_SGIS || target > GL_TEXTURE1_SGIS) {
  282.       gl_error(ctx, GL_INVALID_ENUM, "glMultiTexCoord(target)");
  283.       return;
  284.    }
  285.    if (stride<0) {
  286.       gl_error( ctx, GL_INVALID_VALUE, "glMultiTexCoordPointer(stride)" );
  287.       return;
  288.    }
  289.    if (size<1 || size>4) {
  290.       gl_error( ctx, GL_INVALID_VALUE, "glMultiTexCoordPointer(size)" );
  291.       return;
  292.    }
  293.    texSet = target - GL_TEXTURE0_SGIS;
  294.    switch (type) {
  295.       case GL_SHORT:
  296.          ctx->Array.TexCoordStrideB[texSet] = stride ? stride : size*sizeof(GLshort);
  297.          break;
  298.       case GL_INT:
  299.          ctx->Array.TexCoordStrideB[texSet] = stride ? stride : size*sizeof(GLint);
  300.          break;
  301.       case GL_FLOAT:
  302.          ctx->Array.TexCoordStrideB[texSet] = stride ? stride : size*sizeof(GLfloat);
  303.          break;
  304.       case GL_DOUBLE:
  305.          ctx->Array.TexCoordStrideB[texSet] = stride ? stride : size*sizeof(GLdouble);
  306.          break;
  307.       default:
  308.          gl_error( ctx, GL_INVALID_ENUM, "glMultiTexCoordPointer(type)" );
  309.          return;
  310.    }
  311.    ctx->Array.TexCoordSize[texSet] = size;
  312.    ctx->Array.TexCoordType[texSet] = type;
  313.    ctx->Array.TexCoordStride[texSet] = stride;
  314.    ctx->Array.TexCoordPtr[texSet] = (void *) ptr;
  315. }
  316.  
  317.  
  318.  
  319. void gl_InterleavedTextureCoordSets( GLcontext *ctx, GLint factor )
  320. {
  321.    GLint maxSets = gl_max_texture_coord_sets(ctx);
  322.    if (factor < 1 || factor > maxSets) {
  323.       gl_error( ctx, GL_INVALID_VALUE, "glInterleavedTextureCoordSets" );
  324.       return;
  325.    }
  326.    ctx->Array.TexCoordInterleaveFactor = factor;
  327. }
  328.  
  329.  
  330.  
  331. void gl_EdgeFlagPointer( GLcontext *ctx,
  332.                          GLsizei stride, const GLboolean *ptr )
  333. {
  334.    if (stride<0) {
  335.       gl_error( ctx, GL_INVALID_VALUE, "glEdgeFlagPointer(stride)" );
  336.       return;
  337.    }
  338.    ctx->Array.EdgeFlagStride = stride;
  339.    ctx->Array.EdgeFlagStrideB = stride ? stride : sizeof(GLboolean);
  340.    ctx->Array.EdgeFlagPtr = (GLboolean *) ptr;
  341. }
  342.  
  343.  
  344.  
  345. /*
  346.  * Execute
  347.  */
  348. void gl_ArrayElement( GLcontext *ctx, GLint i )
  349. {
  350.    struct vertex_buffer *VB = ctx->VB;
  351.    GLint count = VB->Count;
  352.    GLuint texSet;
  353.  
  354.    /* copy vertex data into the Vertex Buffer */
  355.  
  356.    if (ctx->Array.NormalEnabled) {
  357.       GLbyte *p = (GLbyte*) ctx->Array.NormalPtr
  358.                   + i * ctx->Array.NormalStrideB;
  359.       switch (ctx->Array.NormalType) {
  360.          case GL_BYTE:
  361.             VB->Normal[count][0] = BYTE_TO_FLOAT( p[0] );
  362.             VB->Normal[count][1] = BYTE_TO_FLOAT( p[1] );
  363.             VB->Normal[count][2] = BYTE_TO_FLOAT( p[2] );
  364.             break;
  365.          case GL_SHORT:
  366.             VB->Normal[count][0] = SHORT_TO_FLOAT( ((GLshort*)p)[0] );
  367.             VB->Normal[count][1] = SHORT_TO_FLOAT( ((GLshort*)p)[1] );
  368.             VB->Normal[count][2] = SHORT_TO_FLOAT( ((GLshort*)p)[2] );
  369.             break;
  370.          case GL_INT:
  371.             VB->Normal[count][0] = INT_TO_FLOAT( ((GLint*)p)[0] );
  372.             VB->Normal[count][1] = INT_TO_FLOAT( ((GLint*)p)[1] );
  373.             VB->Normal[count][2] = INT_TO_FLOAT( ((GLint*)p)[2] );
  374.             break;
  375.          case GL_FLOAT:
  376.             VB->Normal[count][0] = ((GLfloat*)p)[0];
  377.             VB->Normal[count][1] = ((GLfloat*)p)[1];
  378.             VB->Normal[count][2] = ((GLfloat*)p)[2];
  379.             break;
  380.          case GL_DOUBLE:
  381.             VB->Normal[count][0] = ((GLdouble*)p)[0];
  382.             VB->Normal[count][1] = ((GLdouble*)p)[1];
  383.             VB->Normal[count][2] = ((GLdouble*)p)[2];
  384.             break;
  385.          default:
  386.             gl_problem(ctx, "Bad normal type in gl_ArrayElement");
  387.             return;
  388.       }
  389.       VB->MonoNormal = GL_FALSE;
  390.    }
  391.    else {
  392.       VB->Normal[count][0] = ctx->Current.Normal[0];
  393.       VB->Normal[count][1] = ctx->Current.Normal[1];
  394.       VB->Normal[count][2] = ctx->Current.Normal[2];
  395.    } 
  396.  
  397.    /* TODO: directly set VB->Fcolor instead of calling a glColor command */
  398.    if (ctx->Array.ColorEnabled) {
  399.       GLbyte *p = (GLbyte*) ctx->Array.ColorPtr + i * ctx->Array.ColorStrideB;
  400.       switch (ctx->Array.ColorType) {
  401.          case GL_BYTE:
  402.             switch (ctx->Array.ColorSize) {
  403.                case 4:   glColor4bv( (GLbyte*) p );   break;
  404.                case 3:   glColor3bv( (GLbyte*) p );   break;
  405.             }
  406.             break;
  407.          case GL_UNSIGNED_BYTE:
  408.             switch (ctx->Array.ColorSize) {
  409.                case 3:   glColor3ubv( (GLubyte*) p );   break;
  410.                case 4:   glColor4ubv( (GLubyte*) p );   break;
  411.             }
  412.             break;
  413.          case GL_SHORT:
  414.             switch (ctx->Array.ColorSize) {
  415.                case 3:   glColor3sv( (GLshort*) p );   break;
  416.                case 4:   glColor4sv( (GLshort*) p );   break;
  417.             }
  418.             break;
  419.          case GL_UNSIGNED_SHORT:
  420.             switch (ctx->Array.ColorSize) {
  421.                case 3:   glColor3usv( (GLushort*) p );   break;
  422.                case 4:   glColor4usv( (GLushort*) p );   break;
  423.             }
  424.             break;
  425.          case GL_INT:
  426.             switch (ctx->Array.ColorSize) {
  427.                case 3:   glColor3iv( (GLint*) p );   break;
  428.                case 4:   glColor4iv( (GLint*) p );   break;
  429.             }
  430.             break;
  431.          case GL_UNSIGNED_INT:
  432.             switch (ctx->Array.ColorSize) {
  433.                case 3:   glColor3uiv( (GLuint*) p );   break;
  434.                case 4:   glColor4uiv( (GLuint*) p );   break;
  435.             }
  436.             break;
  437.          case GL_FLOAT:
  438.             switch (ctx->Array.ColorSize) {
  439.                case 3:   glColor3fv( (GLfloat*) p );   break;
  440.                case 4:   glColor4fv( (GLfloat*) p );   break;
  441.             }
  442.             break;
  443.          case GL_DOUBLE:
  444.             switch (ctx->Array.ColorSize) {
  445.                case 3:   glColor3dv( (GLdouble*) p );   break;
  446.                case 4:   glColor4dv( (GLdouble*) p );   break;
  447.             }
  448.             break;
  449.          default:
  450.             gl_problem(ctx, "Bad color type in gl_ArrayElement");
  451.             return;
  452.       }
  453.       ctx->VB->MonoColor = GL_FALSE;
  454.    }
  455.  
  456.    /* current color has been updated. store in vertex buffer now */
  457.    {
  458.       COPY_4UBV( VB->Fcolor[count], ctx->Current.ByteColor );
  459.       if (ctx->Light.ColorMaterialEnabled) {
  460.          GLfloat color[4];
  461.          color[0] = ctx->Current.ByteColor[0] * (1.0F / 255.0F);
  462.          color[1] = ctx->Current.ByteColor[1] * (1.0F / 255.0F);
  463.          color[2] = ctx->Current.ByteColor[2] * (1.0F / 255.0F);
  464.          color[3] = ctx->Current.ByteColor[3] * (1.0F / 255.0F);
  465.          gl_set_material( ctx, ctx->Light.ColorMaterialBitmask, color );
  466.       }
  467.    }
  468.  
  469.    if (ctx->Array.IndexEnabled) {
  470.       GLbyte *p = (GLbyte*) ctx->Array.IndexPtr + i * ctx->Array.IndexStrideB;
  471.       switch (ctx->Array.IndexType) {
  472.          case GL_SHORT:
  473.             VB->Findex[count] = (GLuint) (*((GLshort*) p));
  474.             break;
  475.          case GL_INT:
  476.             VB->Findex[count] = (GLuint) (*((GLint*) p));
  477.             break;
  478.          case GL_FLOAT:
  479.             VB->Findex[count] = (GLuint) (*((GLfloat*) p));
  480.             break;
  481.          case GL_DOUBLE:
  482.             VB->Findex[count] = (GLuint) (*((GLdouble*) p));
  483.             break;
  484.          default:
  485.             gl_problem(ctx, "Bad index type in gl_ArrayElement");
  486.             return;
  487.       }
  488.       ctx->VB->MonoColor = GL_FALSE;
  489.    }
  490.    else {
  491.       VB->Findex[count] = ctx->Current.Index;
  492.    }
  493.  
  494.    for (texSet=0; texSet<MAX_TEX_SETS; texSet++) {
  495.        if (ctx->Array.TexCoordEnabled[texSet]) {
  496.           GLbyte *p = (GLbyte*) ctx->Array.TexCoordPtr[texSet]
  497.                       + i * ctx->Array.TexCoordStrideB[texSet];
  498.           VB->MultiTexCoord[texSet][count][1] = 0.0F;
  499.           VB->MultiTexCoord[texSet][count][2] = 0.0F;
  500.           VB->MultiTexCoord[texSet][count][3] = 1.0F;
  501.           switch (ctx->Array.TexCoordType[texSet]) {
  502.              case GL_SHORT:
  503.                 switch (ctx->Array.TexCoordSize[texSet]) {
  504.                    /* FALL THROUGH! */
  505.                    case 4:   VB->MultiTexCoord[texSet][count][3] = ((GLshort*) p)[3];
  506.                    case 3:   VB->MultiTexCoord[texSet][count][2] = ((GLshort*) p)[2];
  507.                    case 2:   VB->MultiTexCoord[texSet][count][1] = ((GLshort*) p)[1];
  508.                    case 1:   VB->MultiTexCoord[texSet][count][0] = ((GLshort*) p)[0];
  509.                 }
  510.                 break;
  511.              case GL_INT:
  512.                 switch (ctx->Array.TexCoordSize[texSet]) {
  513.                    /* FALL THROUGH! */
  514.                    case 4:   VB->MultiTexCoord[texSet][count][3] = ((GLint*) p)[3];
  515.                    case 3:   VB->MultiTexCoord[texSet][count][2] = ((GLint*) p)[2];
  516.                    case 2:   VB->MultiTexCoord[texSet][count][1] = ((GLint*) p)[1];
  517.                    case 1:   VB->MultiTexCoord[texSet][count][0] = ((GLint*) p)[0];
  518.                 }
  519.                 break;
  520.              case GL_FLOAT:
  521.                 switch (ctx->Array.TexCoordSize[texSet]) {
  522.                    /* FALL THROUGH! */
  523.                    case 4:   VB->MultiTexCoord[texSet][count][3] = ((GLfloat*) p)[3];
  524.                    case 3:   VB->MultiTexCoord[texSet][count][2] = ((GLfloat*) p)[2];
  525.                    case 2:   VB->MultiTexCoord[texSet][count][1] = ((GLfloat*) p)[1];
  526.                    case 1:   VB->MultiTexCoord[texSet][count][0] = ((GLfloat*) p)[0];
  527.                 }
  528.                 break;
  529.              case GL_DOUBLE:
  530.                 switch (ctx->Array.TexCoordSize[texSet]) {
  531.                    /* FALL THROUGH! */
  532.                    case 4:   VB->MultiTexCoord[texSet][count][3] = ((GLdouble*) p)[3];
  533.                    case 3:   VB->MultiTexCoord[texSet][count][2] = ((GLdouble*) p)[2];
  534.                    case 2:   VB->MultiTexCoord[texSet][count][1] = ((GLdouble*) p)[1];
  535.                    case 1:   VB->MultiTexCoord[texSet][count][0] = ((GLdouble*) p)[0];
  536.                 }
  537.                 break;
  538.              default:
  539.                 gl_problem(ctx, "Bad texcoord type in gl_ArrayElement");
  540.                 return;
  541.           }
  542.        }
  543.        else {
  544.           COPY_4V( VB->MultiTexCoord[texSet][count], ctx->Current.MultiTexCoord[texSet] );
  545.        }
  546.    }
  547.  
  548.    if (ctx->Array.EdgeFlagEnabled) {
  549.       GLbyte *b = (GLbyte*) ctx->Array.EdgeFlagPtr
  550.                   + i * ctx->Array.EdgeFlagStrideB;
  551.       VB->Edgeflag[count] = *((GLboolean*) b);
  552.    }
  553.    else {
  554.       VB->Edgeflag[count] = ctx->Current.EdgeFlag;
  555.    }
  556.  
  557.    if (ctx->Array.VertexEnabled) {
  558.       GLbyte *b = (GLbyte*) ctx->Array.VertexPtr
  559.                   + i * ctx->Array.VertexStrideB;
  560.       VB->Obj[count][2] = 0.0F;
  561.       VB->Obj[count][3] = 1.0F;
  562.       switch (ctx->Array.VertexType) {
  563.          case GL_SHORT:
  564.             switch (ctx->Array.VertexSize) {
  565.                /* FALL THROUGH */
  566.                case 4:   VB->Obj[count][3] = ((GLshort*) b)[3];
  567.                case 3:   VB->Obj[count][2] = ((GLshort*) b)[2];
  568.                case 2:   VB->Obj[count][1] = ((GLshort*) b)[1];
  569.                          VB->Obj[count][0] = ((GLshort*) b)[0];
  570.             }
  571.             break;
  572.          case GL_INT:
  573.             switch (ctx->Array.VertexSize) {
  574.                /* FALL THROUGH */
  575.                case 4:   VB->Obj[count][3] = ((GLint*) b)[3];
  576.                case 3:   VB->Obj[count][2] = ((GLint*) b)[2];
  577.                case 2:   VB->Obj[count][1] = ((GLint*) b)[1];
  578.                          VB->Obj[count][0] = ((GLint*) b)[0];
  579.             }
  580.             break;
  581.          case GL_FLOAT:
  582.             switch (ctx->Array.VertexSize) {
  583.                /* FALL THROUGH */
  584.                case 4:   VB->Obj[count][3] = ((GLfloat*) b)[3];
  585.                case 3:   VB->Obj[count][2] = ((GLfloat*) b)[2];
  586.                case 2:   VB->Obj[count][1] = ((GLfloat*) b)[1];
  587.                          VB->Obj[count][0] = ((GLfloat*) b)[0];
  588.             }
  589.             break;
  590.          case GL_DOUBLE:
  591.             switch (ctx->Array.VertexSize) {
  592.                /* FALL THROUGH */
  593.                case 4:   VB->Obj[count][3] = ((GLdouble*) b)[3];
  594.                case 3:   VB->Obj[count][2] = ((GLdouble*) b)[2];
  595.                case 2:   VB->Obj[count][1] = ((GLdouble*) b)[1];
  596.                          VB->Obj[count][0] = ((GLdouble*) b)[0];
  597.             }
  598.             break;
  599.          default:
  600.             gl_problem(ctx, "Bad vertex type in gl_ArrayElement");
  601.             return;
  602.       }
  603.  
  604.       /* Only store vertex if Vertex array pointer is enabled */
  605.       count++;
  606.       VB->Count = count;
  607.       if (count==VB_MAX) {
  608.          gl_transform_vb_part1( ctx, GL_FALSE );
  609.       }
  610.  
  611.    }
  612.    else {
  613.       /* vertex array pointer not enabled: no vertex to process */
  614.    }
  615. }
  616.  
  617.  
  618.  
  619.  
  620. /*
  621.  * Save into display list
  622.  * Use external API entry points since speed isn't too important here
  623.  * and makes the code simpler.  Also, if GL_COMPILE_AND_EXECUTE then
  624.  * execute will happen too.
  625.  */
  626. void gl_save_ArrayElement( GLcontext *ctx, GLint i )
  627. {
  628.    GLuint texSet;
  629.    if (ctx->Array.NormalEnabled) {
  630.       GLbyte *p = (GLbyte*) ctx->Array.NormalPtr
  631.                   + i * ctx->Array.NormalStrideB;
  632.       switch (ctx->Array.NormalType) {
  633.          case GL_BYTE:
  634.             glNormal3bv( (GLbyte*) p );
  635.             break;
  636.          case GL_SHORT:
  637.             glNormal3sv( (GLshort*) p );
  638.             break;
  639.          case GL_INT:
  640.             glNormal3iv( (GLint*) p );
  641.             break;
  642.          case GL_FLOAT:
  643.             glNormal3fv( (GLfloat*) p );
  644.             break;
  645.          case GL_DOUBLE:
  646.             glNormal3dv( (GLdouble*) p );
  647.             break;
  648.          default:
  649.             gl_problem(ctx, "Bad normal type in gl_save_ArrayElement");
  650.             return;
  651.       }
  652.    }
  653.  
  654.    if (ctx->Array.ColorEnabled) {
  655.       GLbyte *p = (GLbyte*) ctx->Array.ColorPtr + i * ctx->Array.ColorStrideB;
  656.       switch (ctx->Array.ColorType) {
  657.          case GL_BYTE:
  658.             switch (ctx->Array.ColorSize) {
  659.                case 3:   glColor3bv( (GLbyte*) p );   break;
  660.                case 4:   glColor4bv( (GLbyte*) p );   break;
  661.             }
  662.             break;
  663.          case GL_UNSIGNED_BYTE:
  664.             switch (ctx->Array.ColorSize) {
  665.                case 3:   glColor3ubv( (GLubyte*) p );   break;
  666.                case 4:   glColor4ubv( (GLubyte*) p );   break;
  667.             }
  668.             break;
  669.          case GL_SHORT:
  670.             switch (ctx->Array.ColorSize) {
  671.                case 3:   glColor3sv( (GLshort*) p );   break;
  672.                case 4:   glColor4sv( (GLshort*) p );   break;
  673.             }
  674.             break;
  675.          case GL_UNSIGNED_SHORT:
  676.             switch (ctx->Array.ColorSize) {
  677.                case 3:   glColor3usv( (GLushort*) p );   break;
  678.                case 4:   glColor4usv( (GLushort*) p );   break;
  679.             }
  680.             break;
  681.          case GL_INT:
  682.             switch (ctx->Array.ColorSize) {
  683.                case 3:   glColor3iv( (GLint*) p );   break;
  684.                case 4:   glColor4iv( (GLint*) p );   break;
  685.             }
  686.             break;
  687.          case GL_UNSIGNED_INT:
  688.             switch (ctx->Array.ColorSize) {
  689.                case 3:   glColor3uiv( (GLuint*) p );   break;
  690.                case 4:   glColor4uiv( (GLuint*) p );   break;
  691.             }
  692.             break;
  693.          case GL_FLOAT:
  694.             switch (ctx->Array.ColorSize) {
  695.                case 3:   glColor3fv( (GLfloat*) p );   break;
  696.                case 4:   glColor4fv( (GLfloat*) p );   break;
  697.             }
  698.             break;
  699.          case GL_DOUBLE:
  700.             switch (ctx->Array.ColorSize) {
  701.                case 3:   glColor3dv( (GLdouble*) p );   break;
  702.                case 4:   glColor4dv( (GLdouble*) p );   break;
  703.             }
  704.             break;
  705.          default:
  706.             gl_problem(ctx, "Bad color type in gl_save_ArrayElement");
  707.             return;
  708.       }
  709.    }
  710.  
  711.    if (ctx->Array.IndexEnabled) {
  712.       GLbyte *p = (GLbyte*) ctx->Array.IndexPtr + i * ctx->Array.IndexStrideB;
  713.       switch (ctx->Array.IndexType) {
  714.          case GL_SHORT:
  715.             glIndexsv( (GLshort*) p );
  716.             break;
  717.          case GL_INT:
  718.             glIndexiv( (GLint*) p );
  719.             break;
  720.          case GL_FLOAT:
  721.             glIndexfv( (GLfloat*) p );
  722.             break;
  723.          case GL_DOUBLE:
  724.             glIndexdv( (GLdouble*) p );
  725.             break;
  726.          default:
  727.             gl_problem(ctx, "Bad index type in gl_save_ArrayElement");
  728.             return;
  729.       }
  730.    }
  731.  
  732.    for (texSet=0; texSet<MAX_TEX_SETS; texSet++) {
  733.       if (ctx->Array.TexCoordEnabled[texSet]) {
  734.          GLbyte *p = (GLbyte*) ctx->Array.TexCoordPtr[texSet]
  735.                      + i * ctx->Array.TexCoordStrideB[texSet];
  736.          GLenum target = (GLenum) (GL_TEXTURE0_SGIS + texSet);
  737.          switch (ctx->Array.TexCoordType[texSet]) {
  738.             case GL_SHORT:
  739.                switch (ctx->Array.TexCoordSize[texSet]) {
  740.                   case 1:   glMultiTexCoord1svSGIS( target, (GLshort*) p );   break;
  741.                   case 2:   glMultiTexCoord2svSGIS( target, (GLshort*) p );   break;
  742.                   case 3:   glMultiTexCoord3svSGIS( target, (GLshort*) p );   break;
  743.                   case 4:   glMultiTexCoord4svSGIS( target, (GLshort*) p );   break;
  744.                }
  745.                break;
  746.             case GL_INT:
  747.                switch (ctx->Array.TexCoordSize[texSet]) {
  748.                   case 1:   glMultiTexCoord1ivSGIS( target, (GLint*) p );   break;
  749.                   case 2:   glMultiTexCoord2ivSGIS( target, (GLint*) p );   break;
  750.                   case 3:   glMultiTexCoord3ivSGIS( target, (GLint*) p );   break;
  751.                   case 4:   glMultiTexCoord4ivSGIS( target, (GLint*) p );   break;
  752.                }
  753.                break;
  754.             case GL_FLOAT:
  755.                switch (ctx->Array.TexCoordSize[texSet]) {
  756.                   case 1:   glMultiTexCoord1fvSGIS( target, (GLfloat*) p );   break;
  757.                   case 2:   glMultiTexCoord2fvSGIS( target, (GLfloat*) p );   break;
  758.                   case 3:   glMultiTexCoord3fvSGIS( target, (GLfloat*) p );   break;
  759.                   case 4:   glMultiTexCoord4fvSGIS( target, (GLfloat*) p );   break;
  760.                }
  761.                break;
  762.             case GL_DOUBLE:
  763.                switch (ctx->Array.TexCoordSize[texSet]) {
  764.                   case 1:   glMultiTexCoord1dvSGIS( target, (GLdouble*) p );   break;
  765.                   case 2:   glMultiTexCoord2dvSGIS( target, (GLdouble*) p );   break;
  766.                   case 3:   glMultiTexCoord3dvSGIS( target, (GLdouble*) p );   break;
  767.                   case 4:   glMultiTexCoord4dvSGIS( target, (GLdouble*) p );   break;
  768.                }
  769.                break;
  770.             default:
  771.                gl_problem(ctx, "Bad texcoord type in gl_save_ArrayElement");
  772.                return;
  773.          }
  774.       }
  775.    }
  776.  
  777.    if (ctx->Array.EdgeFlagEnabled) {
  778.       GLbyte *b = (GLbyte*) ctx->Array.EdgeFlagPtr + i * ctx->Array.EdgeFlagStrideB;
  779.       glEdgeFlagv( (GLboolean*) b );
  780.    }
  781.  
  782.    if (ctx->Array.VertexEnabled) {
  783.       GLbyte *b = (GLbyte*) ctx->Array.VertexPtr
  784.                   + i * ctx->Array.VertexStrideB;
  785.       switch (ctx->Array.VertexType) {
  786.          case GL_SHORT:
  787.             switch (ctx->Array.VertexSize) {
  788.                case 2:   glVertex2sv( (GLshort*) b );   break;
  789.                case 3:   glVertex3sv( (GLshort*) b );   break;
  790.                case 4:   glVertex4sv( (GLshort*) b );   break;
  791.             }
  792.             break;
  793.          case GL_INT:
  794.             switch (ctx->Array.VertexSize) {
  795.                case 2:   glVertex2iv( (GLint*) b );   break;
  796.                case 3:   glVertex3iv( (GLint*) b );   break;
  797.                case 4:   glVertex4iv( (GLint*) b );   break;
  798.             }
  799.             break;
  800.          case GL_FLOAT:
  801.             switch (ctx->Array.VertexSize) {
  802.                case 2:   glVertex2fv( (GLfloat*) b );   break;
  803.                case 3:   glVertex3fv( (GLfloat*) b );   break;
  804.                case 4:   glVertex4fv( (GLfloat*) b );   break;
  805.             }
  806.             break;
  807.          case GL_DOUBLE:
  808.             switch (ctx->Array.VertexSize) {
  809.                case 2:   glVertex2dv( (GLdouble*) b );   break;
  810.                case 3:   glVertex3dv( (GLdouble*) b );   break;
  811.                case 4:   glVertex4dv( (GLdouble*) b );   break;
  812.             }
  813.             break;
  814.          default:
  815.             gl_problem(ctx, "Bad vertex type in gl_save_ArrayElement");
  816.             return;
  817.       }
  818.    }
  819. }
  820.  
  821.  
  822.  
  823. /*
  824.  * Execute
  825.  */
  826. void gl_DrawArrays( GLcontext *ctx,
  827.                     GLenum mode, GLint first, GLsizei count )
  828. {
  829.    struct vertex_buffer* VB = ctx->VB;
  830.    GLuint texSet = ctx->Texture.CurrentSet;
  831.    GLint i;
  832.    GLboolean need_edges;
  833.  
  834.    if (INSIDE_BEGIN_END(ctx)) {
  835.       gl_error( ctx, GL_INVALID_OPERATION, "glDrawArrays" );
  836.       return;
  837.    }
  838.    if (count<0) {
  839.       gl_error( ctx, GL_INVALID_VALUE, "glDrawArrays(count)" );
  840.       return;
  841.    }
  842.  
  843.    if (ctx->Primitive==GL_TRIANGLES || ctx->Primitive==GL_QUADS
  844.        || ctx->Primitive==GL_POLYGON) {
  845.       need_edges = GL_TRUE;
  846.    }
  847.    else {
  848.       need_edges = GL_FALSE;
  849.    }
  850.  
  851.    if (!ctx->Light.Enabled
  852.        && !ctx->Texture.Enabled
  853.        && ctx->Array.VertexEnabled && ctx->Array.VertexType==GL_FLOAT
  854.        && ctx->Array.VertexStride==0 && ctx->Array.VertexSize==3
  855.        && !ctx->Array.NormalEnabled
  856.        && !ctx->Array.ColorEnabled
  857.        && !ctx->Array.IndexEnabled
  858.        && !ctx->Array.TexCoordEnabled[texSet]
  859.        && !ctx->Array.EdgeFlagEnabled) {
  860.       /*
  861.        * SPECIAL CASE:  glVertex3fv() with no lighting
  862.        */
  863.       GLfloat (*vptr)[3];
  864.       GLint remaining;
  865.  
  866.       gl_Begin( ctx, mode );
  867.  
  868.       remaining = count;
  869.       vptr = (GLfloat (*)[3]) ctx->Array.VertexPtr + 3 * first;
  870.       while (remaining>0) {
  871.          GLint vbspace, n;
  872.  
  873.          vbspace = VB_MAX - VB->Start;
  874.          n = MIN2( vbspace, remaining );
  875.  
  876.          gl_xform_points_3fv( n, VB->Eye+VB->Start, ctx->ModelViewMatrix, vptr );
  877.  
  878.          /* assign vertex colors */
  879.          {
  880.             GLint i, start = VB->Start;
  881.             for (i=0;i<n;i++) {
  882.                COPY_4UBV( VB->Fcolor[start+i], ctx->Current.ByteColor );
  883.             }
  884.          }
  885.  
  886.          /* assign polygon edgeflags */
  887.          if (need_edges) {
  888.             GLint i;
  889.             for (i=0;i<n;i++) {
  890.                VB->Edgeflag[VB->Start+i] = ctx->Current.EdgeFlag;
  891.             }
  892.          }
  893.  
  894.          remaining -= n;
  895.  
  896.          VB->MonoNormal = GL_FALSE;
  897.          VB->Count = VB->Start + n;
  898.          gl_transform_vb_part2( ctx, remaining==0 ? GL_TRUE : GL_FALSE );
  899.  
  900.          vptr += n;
  901.       }
  902.  
  903.       gl_End( ctx );
  904.    }
  905.    else if (!ctx->CompileFlag
  906.        && ctx->Light.Enabled
  907.        && !ctx->Texture.Enabled
  908.        && ctx->Array.VertexEnabled && ctx->Array.VertexType==GL_FLOAT
  909.        && ctx->Array.VertexStride==0 && ctx->Array.VertexSize==4
  910.        && ctx->Array.NormalEnabled && ctx->Array.NormalType==GL_FLOAT
  911.        && ctx->Array.NormalStride==0
  912.        && !ctx->Array.ColorEnabled
  913.        && !ctx->Array.IndexEnabled
  914.        && !ctx->Array.TexCoordEnabled[texSet]
  915.        && !ctx->Array.EdgeFlagEnabled) {
  916.       /*
  917.        * SPECIAL CASE:  glNormal3fv();  glVertex4fv();  with lighting
  918.        */
  919.       GLfloat (*vptr)[4], (*nptr)[3];
  920.       GLint remaining;
  921.  
  922.       gl_Begin( ctx, mode );
  923.  
  924.       remaining = count;
  925.       vptr = (GLfloat (*)[4]) ctx->Array.VertexPtr + 4 * first;
  926.       nptr = (GLfloat (*)[3]) ctx->Array.NormalPtr + 3 * first;
  927.       while (remaining>0) {
  928.          GLint vbspace, n;
  929.  
  930.          vbspace = VB_MAX - VB->Start;
  931.          n = MIN2( vbspace, remaining );
  932.  
  933.          gl_xform_points_4fv( n, VB->Eye+VB->Start, ctx->ModelViewMatrix, vptr );
  934.          gl_xform_normals_3fv( n, VB->Normal+VB->Start, ctx->ModelViewInv, nptr,
  935.                                ctx->Transform.Normalize,
  936.                                ctx->Transform.RescaleNormals );
  937.  
  938.          /* assign polygon edgeflags */
  939.          if (need_edges) {
  940.             GLint i;
  941.             for (i=0;i<n;i++) {
  942.                VB->Edgeflag[VB->Start+i] = ctx->Current.EdgeFlag;
  943.             }
  944.          }
  945.  
  946.          remaining -= n;
  947.  
  948.          VB->MonoNormal = GL_FALSE;
  949.          VB->Count = VB->Start + n;
  950.          gl_transform_vb_part2( ctx, remaining==0 ? GL_TRUE : GL_FALSE );
  951.  
  952.          vptr += n;
  953.          nptr += n;
  954.       }
  955.  
  956.       gl_End( ctx );
  957.    }
  958.    else if (!ctx->CompileFlag
  959.        && ctx->Light.Enabled
  960.        && !ctx->Texture.Enabled
  961.        && ctx->Array.VertexEnabled && ctx->Array.VertexType==GL_FLOAT
  962.        && ctx->Array.VertexStride==0 && ctx->Array.VertexSize==3
  963.        && ctx->Array.NormalEnabled && ctx->Array.NormalType==GL_FLOAT
  964.        && ctx->Array.NormalStride==0
  965.        && !ctx->Array.ColorEnabled
  966.        && !ctx->Array.IndexEnabled
  967.        && !ctx->Array.TexCoordEnabled[texSet]
  968.        && !ctx->Array.EdgeFlagEnabled) {
  969.       /*
  970.        * SPECIAL CASE:  glNormal3fv();  glVertex3fv();  with lighting
  971.        */
  972.       GLfloat (*vptr)[3], (*nptr)[3];
  973.       GLint remaining;
  974.  
  975.       gl_Begin( ctx, mode );
  976.  
  977.       remaining = count;
  978.       vptr = (GLfloat (*)[3]) ctx->Array.VertexPtr + 3 * first;
  979.       nptr = (GLfloat (*)[3]) ctx->Array.NormalPtr + 3 * first;
  980.       while (remaining>0) {
  981.          GLint vbspace, n;
  982.  
  983.          vbspace = VB_MAX - VB->Start;
  984.          n = MIN2( vbspace, remaining );
  985.  
  986.          gl_xform_points_3fv( n, VB->Eye+VB->Start, ctx->ModelViewMatrix, vptr );
  987.          gl_xform_normals_3fv( n, VB->Normal+VB->Start, ctx->ModelViewInv, nptr,
  988.                                ctx->Transform.Normalize,
  989.                                ctx->Transform.RescaleNormals );
  990.  
  991.          /* assign polygon edgeflags */
  992.          if (need_edges) {
  993.             GLint i;
  994.             for (i=0;i<n;i++) {
  995.                VB->Edgeflag[VB->Start+i] = ctx->Current.EdgeFlag;
  996.             }
  997.          }
  998.  
  999.          remaining -= n;
  1000.  
  1001.          VB->MonoNormal = GL_FALSE;
  1002.          VB->Count = VB->Start + n;
  1003.          gl_transform_vb_part2( ctx, remaining==0 ? GL_TRUE : GL_FALSE );
  1004.  
  1005.          vptr += n;
  1006.          nptr += n;
  1007.       }
  1008.  
  1009.       gl_End( ctx );
  1010.    }
  1011.    else {
  1012.       /*
  1013.        * GENERAL CASE:
  1014.        */
  1015.       gl_Begin( ctx, mode );
  1016.       for (i=0;i<count;i++) {
  1017.          gl_ArrayElement( ctx, first+i );
  1018.       }
  1019.       gl_End( ctx );
  1020.    }
  1021. }
  1022.  
  1023.  
  1024.  
  1025. /*
  1026.  * Save into a display list
  1027.  */
  1028. void gl_save_DrawArrays( GLcontext *ctx,
  1029.                          GLenum mode, GLint first, GLsizei count )
  1030. {
  1031.    GLint i;
  1032.  
  1033.    if (INSIDE_BEGIN_END(ctx)) {
  1034.       gl_error( ctx, GL_INVALID_OPERATION, "glDrawArrays" );
  1035.       return;
  1036.    }
  1037.    if (count<0) {
  1038.       gl_error( ctx, GL_INVALID_VALUE, "glDrawArrays(count)" );
  1039.       return;
  1040.    }
  1041.    switch (mode) {
  1042.       case GL_POINTS:
  1043.       case GL_LINES:
  1044.       case GL_LINE_STRIP:
  1045.       case GL_LINE_LOOP:
  1046.       case GL_TRIANGLES:
  1047.       case GL_TRIANGLE_STRIP:
  1048.       case GL_TRIANGLE_FAN:
  1049.       case GL_QUADS:
  1050.       case GL_QUAD_STRIP:
  1051.       case GL_POLYGON:
  1052.          /* OK */
  1053.          break;
  1054.       default:
  1055.          gl_error( ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" );
  1056.          return;
  1057.    }
  1058.  
  1059.    /* Note: this will do compile AND execute if needed */
  1060.    gl_save_Begin( ctx, mode );
  1061.    for (i=0;i<count;i++) {
  1062.       gl_save_ArrayElement( ctx, first+i );
  1063.    }
  1064.    gl_save_End( ctx );
  1065. }
  1066.  
  1067.  
  1068.  
  1069.  
  1070. /*
  1071.  * Execute only
  1072.  */
  1073. void gl_DrawElements( GLcontext *ctx,
  1074.                       GLenum mode, GLsizei count,
  1075.                       GLenum type, const GLvoid *indices )
  1076. {
  1077.    
  1078.    if (INSIDE_BEGIN_END(ctx)) {
  1079.       gl_error( ctx, GL_INVALID_OPERATION, "glDrawElements" );
  1080.       return;
  1081.    }
  1082.    if (count<0) {
  1083.       gl_error( ctx, GL_INVALID_VALUE, "glDrawElements(count)" );
  1084.       return;
  1085.    }
  1086.    switch (mode) {
  1087.       case GL_POINTS:
  1088.       case GL_LINES:
  1089.       case GL_LINE_STRIP:
  1090.       case GL_LINE_LOOP:
  1091.       case GL_TRIANGLES:
  1092.       case GL_TRIANGLE_STRIP:
  1093.       case GL_TRIANGLE_FAN:
  1094.       case GL_QUADS:
  1095.       case GL_QUAD_STRIP:
  1096.       case GL_POLYGON:
  1097.          /* OK */
  1098.          break;
  1099.       default:
  1100.          gl_error( ctx, GL_INVALID_ENUM, "glDrawArrays(mode)" );
  1101.          return;
  1102.    }
  1103.    switch (type) {
  1104.       case GL_UNSIGNED_BYTE:
  1105.          {
  1106.             GLubyte *ub_indices = (GLubyte *) indices;
  1107.             GLint i;
  1108.             gl_Begin( ctx, mode );
  1109.             for (i=0;i<count;i++) {
  1110.                gl_ArrayElement( ctx, (GLint) ub_indices[i] );
  1111.             }
  1112.             gl_End( ctx );
  1113.          }
  1114.          break;
  1115.       case GL_UNSIGNED_SHORT:
  1116.          {
  1117.             GLushort *us_indices = (GLushort *) indices;
  1118.             GLint i;
  1119.             gl_Begin( ctx, mode );
  1120.             for (i=0;i<count;i++) {
  1121.                gl_ArrayElement( ctx, (GLint) us_indices[i] );
  1122.             }
  1123.             gl_End( ctx );
  1124.          }
  1125.          break;
  1126.       case GL_UNSIGNED_INT:
  1127.          {
  1128.             GLuint *ui_indices = (GLuint *) indices;
  1129.             GLint i;
  1130.             gl_Begin( ctx, mode );
  1131.             for (i=0;i<count;i++) {
  1132.                gl_ArrayElement( ctx, (GLint) ui_indices[i] );
  1133.             }
  1134.             gl_End( ctx );
  1135.          }
  1136.          break;
  1137.       default:
  1138.          gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
  1139.          return;
  1140.    }
  1141. }
  1142.  
  1143.  
  1144.  
  1145.  
  1146. /*
  1147.  * Save (and perhaps execute)
  1148.  */
  1149. void gl_save_DrawElements( GLcontext *ctx,
  1150.                            GLenum mode, GLsizei count,
  1151.                            GLenum type, const GLvoid *indices )
  1152. {
  1153.    switch (type) {
  1154.       case GL_UNSIGNED_BYTE:
  1155.          {
  1156.             GLubyte *ub_indices = (GLubyte *) indices;
  1157.             GLint i;
  1158.             gl_save_Begin( ctx, mode );
  1159.             for (i=0;i<count;i++) {
  1160.                gl_save_ArrayElement( ctx, (GLint) ub_indices[i] );
  1161.             }
  1162.             gl_save_End( ctx );
  1163.          }
  1164.          break;
  1165.       case GL_UNSIGNED_SHORT:
  1166.          {
  1167.             GLushort *us_indices = (GLushort *) indices;
  1168.             GLint i;
  1169.             gl_save_Begin( ctx, mode );
  1170.             for (i=0;i<count;i++) {
  1171.                gl_save_ArrayElement( ctx, (GLint) us_indices[i] );
  1172.             }
  1173.             gl_save_End( ctx );
  1174.          }
  1175.          break;
  1176.       case GL_UNSIGNED_INT:
  1177.          {
  1178.             GLuint *ui_indices = (GLuint *) indices;
  1179.             GLint i;
  1180.             gl_save_Begin( ctx, mode );
  1181.             for (i=0;i<count;i++) {
  1182.                gl_save_ArrayElement( ctx, (GLint) ui_indices[i] );
  1183.             }
  1184.             gl_save_End( ctx );
  1185.          }
  1186.          break;
  1187.       default:
  1188.          gl_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" );
  1189.          return;
  1190.    }
  1191. }
  1192.  
  1193.  
  1194.  
  1195. void gl_InterleavedArrays( GLcontext *ctx,
  1196.                            GLenum format, GLsizei stride,
  1197.                            const GLvoid *pointer )
  1198. {
  1199.    GLboolean tflag, cflag, nflag;  /* enable/disable flags */
  1200.    GLint tcomps, ccomps, vcomps;   /* components per texcoord, color, vertex */
  1201.    GLenum ctype;                   /* color type */
  1202.    GLint coffset, noffset, voffset;/* color, normal, vertex offsets */
  1203.    GLint defstride;                /* default stride */
  1204.    GLint c, f;
  1205.    GLint coordSetSave;
  1206.  
  1207.    f = sizeof(GLfloat);
  1208.    c = f * ((4*sizeof(GLubyte) + (f-1)) / f);
  1209.  
  1210.    if (stride<0) {
  1211.       gl_error( ctx, GL_INVALID_VALUE, "glInterleavedArrays(stride)" );
  1212.       return;
  1213.    }
  1214.  
  1215.    switch (format) {
  1216.       case GL_V2F:
  1217.          tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_FALSE;
  1218.          tcomps = 0;  ccomps = 0;  vcomps = 2;
  1219.          voffset = 0;
  1220.          defstride = 2*f;
  1221.          break;
  1222.       case GL_V3F:
  1223.          tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_FALSE;
  1224.          tcomps = 0;  ccomps = 0;  vcomps = 3;
  1225.          voffset = 0;
  1226.          defstride = 3*f;
  1227.          break;
  1228.       case GL_C4UB_V2F:
  1229.          tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
  1230.          tcomps = 0;  ccomps = 4;  vcomps = 2;
  1231.          ctype = GL_UNSIGNED_BYTE;
  1232.          coffset = 0;
  1233.          voffset = c;
  1234.          defstride = c + 2*f;
  1235.          break;
  1236.       case GL_C4UB_V3F:
  1237.          tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
  1238.          tcomps = 0;  ccomps = 4;  vcomps = 3;
  1239.          ctype = GL_UNSIGNED_BYTE;
  1240.          coffset = 0;
  1241.          voffset = c;
  1242.          defstride = c + 3*f;
  1243.          break;
  1244.       case GL_C3F_V3F:
  1245.          tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_FALSE;
  1246.          tcomps = 0;  ccomps = 3;  vcomps = 3;
  1247.          ctype = GL_FLOAT;
  1248.          coffset = 0;
  1249.          voffset = 3*f;
  1250.          defstride = 6*f;
  1251.          break;
  1252.       case GL_N3F_V3F:
  1253.          tflag = GL_FALSE;  cflag = GL_FALSE;  nflag = GL_TRUE;
  1254.          tcomps = 0;  ccomps = 0;  vcomps = 3;
  1255.          noffset = 0;
  1256.          voffset = 3*f;
  1257.          defstride = 6*f;
  1258.          break;
  1259.       case GL_C4F_N3F_V3F:
  1260.          tflag = GL_FALSE;  cflag = GL_TRUE;  nflag = GL_TRUE;
  1261.          tcomps = 0;  ccomps = 4;  vcomps = 3;
  1262.          ctype = GL_FLOAT;
  1263.          coffset = 0;
  1264.          noffset = 4*f;
  1265.          voffset = 7*f;
  1266.          defstride = 10*f;
  1267.          break;
  1268.       case GL_T2F_V3F:
  1269.          tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_FALSE;
  1270.          tcomps = 2;  ccomps = 0;  vcomps = 3;
  1271.          voffset = 2*f;
  1272.          defstride = 5*f;
  1273.          break;
  1274.       case GL_T4F_V4F:
  1275.          tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_FALSE;
  1276.          tcomps = 4;  ccomps = 0;  vcomps = 4;
  1277.          voffset = 4*f;
  1278.          defstride = 8*f;
  1279.          break;
  1280.       case GL_T2F_C4UB_V3F:
  1281.          tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_FALSE;
  1282.          tcomps = 2;  ccomps = 4;  vcomps = 3;
  1283.          ctype = GL_UNSIGNED_BYTE;
  1284.          coffset = 2*f;
  1285.          voffset = c+2*f;
  1286.          defstride = c+5*f;
  1287.          break;
  1288.       case GL_T2F_C3F_V3F:
  1289.          tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_FALSE;
  1290.          tcomps = 2;  ccomps = 3;  vcomps = 3;
  1291.          ctype = GL_FLOAT;
  1292.          coffset = 2*f;
  1293.          voffset = 5*f;
  1294.          defstride = 8*f;
  1295.          break;
  1296.       case GL_T2F_N3F_V3F:
  1297.          tflag = GL_TRUE;  cflag = GL_FALSE;  nflag = GL_TRUE;
  1298.          tcomps = 2;  ccomps = 0;  vcomps = 3;
  1299.          noffset = 2*f;
  1300.          voffset = 5*f;
  1301.          defstride = 8*f;
  1302.          break;
  1303.       case GL_T2F_C4F_N3F_V3F:
  1304.          tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_TRUE;
  1305.          tcomps = 2;  ccomps = 4;  vcomps = 3;
  1306.          ctype = GL_FLOAT;
  1307.          coffset = 2*f;
  1308.          noffset = 6*f;
  1309.          voffset = 9*f;
  1310.          defstride = 12*f;
  1311.          break;
  1312.       case GL_T4F_C4F_N3F_V4F:
  1313.          tflag = GL_TRUE;  cflag = GL_TRUE;  nflag = GL_TRUE;
  1314.          tcomps = 4;  ccomps = 4;  vcomps = 4;
  1315.          ctype = GL_FLOAT;
  1316.          coffset = 4*f;
  1317.          noffset = 8*f;
  1318.          voffset = 11*f;
  1319.          defstride = 15*f;
  1320.          break;
  1321.       default:
  1322.          gl_error( ctx, GL_INVALID_ENUM, "glInterleavedArrays(format)" );
  1323.          return;
  1324.    }
  1325.  
  1326.    if (stride==0) {
  1327.       stride = defstride;
  1328.    }
  1329.  
  1330.    gl_DisableClientState( ctx, GL_EDGE_FLAG_ARRAY );
  1331.    gl_DisableClientState( ctx, GL_INDEX_ARRAY );
  1332.  
  1333.    /* Texcoords */
  1334.    coordSetSave = ctx->TexCoordSet;
  1335.    if (tflag) {
  1336.       GLint i;
  1337.       GLint factor = ctx->Array.TexCoordInterleaveFactor;
  1338.       for (i = 0; i < factor; i++) {
  1339.          gl_SelectTextureCoordSet( ctx, GL_TEXTURE0_EXT + i );
  1340.          gl_EnableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
  1341.          gl_TexCoordPointer( ctx, tcomps, GL_FLOAT, stride,
  1342.                              (GLubyte *) pointer + i * coffset );
  1343.       }
  1344.       for (i = factor; i < MAX_TEX_COORD_SETS; i++) {
  1345.          gl_SelectTextureCoordSet( ctx, GL_TEXTURE0_EXT + i );
  1346.          gl_DisableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
  1347.       }
  1348.    }
  1349.    else {
  1350.       GLint i;
  1351.       for (i = 0; i < MAX_TEX_COORD_SETS; i++) {
  1352.          gl_SelectTextureCoordSet( ctx, GL_TEXTURE0_EXT + i );
  1353.          gl_DisableClientState( ctx, GL_TEXTURE_COORD_ARRAY );
  1354.       }
  1355.    }
  1356.    /* Restore texture coordinate set index */
  1357.    gl_SelectTextureCoordSet( ctx, GL_TEXTURE0_EXT + coordSetSave );
  1358.  
  1359.  
  1360.    /* Color */
  1361.    if (cflag) {
  1362.       gl_EnableClientState( ctx, GL_COLOR_ARRAY );
  1363.       gl_ColorPointer( ctx, ccomps, ctype, stride,
  1364.                        (GLubyte*) pointer + coffset );
  1365.    }
  1366.    else {
  1367.       gl_DisableClientState( ctx, GL_COLOR_ARRAY );
  1368.    }
  1369.  
  1370.  
  1371.    /* Normals */
  1372.    if (nflag) {
  1373.       gl_EnableClientState( ctx, GL_NORMAL_ARRAY );
  1374.       gl_NormalPointer( ctx, GL_FLOAT, stride,
  1375.                         (GLubyte*) pointer + noffset );
  1376.    }
  1377.    else {
  1378.       gl_DisableClientState( ctx, GL_NORMAL_ARRAY );
  1379.    }
  1380.  
  1381.    gl_EnableClientState( ctx, GL_VERTEX_ARRAY );
  1382.    gl_VertexPointer( ctx, vcomps, GL_FLOAT, stride,
  1383.                      (GLubyte *) pointer + voffset );
  1384. }
  1385.  
  1386.  
  1387.  
  1388. void gl_save_InterleavedArrays( GLcontext *ctx,
  1389.                                 GLenum format, GLsizei stride,
  1390.                                 const GLvoid *pointer )
  1391. {
  1392.    /* Just execute since client-side state changes aren't put in
  1393.     * display lists.
  1394.     */
  1395.    gl_InterleavedArrays( ctx, format, stride, pointer );
  1396. }
  1397.  
  1398.  
  1399.  
  1400. void gl_DrawRangeElements( GLcontext *ctx, GLenum mode, GLuint start,
  1401.                            GLuint end, GLsizei count, GLenum type,
  1402.                            const GLvoid *indices )
  1403. {
  1404.    /* XXX TODO optimize this function someday- it would be worthwhile */
  1405.    if (end < start) {
  1406.       gl_error(ctx, GL_INVALID_VALUE, "glDrawRangeElements( end < start )");
  1407.       return;
  1408.    }
  1409.    (void) start;
  1410.    (void) end;
  1411.    gl_DrawElements( ctx, mode, count, type, indices );
  1412. }
  1413.  
  1414.  
  1415. void gl_save_DrawRangeElements( GLcontext *ctx, GLenum mode,
  1416.                                 GLuint start, GLuint end, GLsizei count,
  1417.                                 GLenum type, const GLvoid *indices )
  1418. {
  1419.    /* XXX TODO optimize this function someday- it would be worthwhile */
  1420.    (void) start;
  1421.    (void) end;
  1422.    gl_save_DrawElements( ctx, mode, count, type, indices );
  1423. }
  1424.